//////////////////////////////////////////
//
//	FlexInc. 2010
//	http://www.loziosecchi.it/flex_inc
//	http://twitter.com/loziosecchi
//
//////////////////////////////////////////

package flexInc.spark.components
{
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;
	
	import flexInc.spark.components.supportClasses.ImageRotatorBase;
	import flexInc.spark.effects.AnimateTransitionShaderUtils;
	
	import mx.events.FlexEvent;
	import mx.states.Transition;
	
	import spark.components.Button;
	import spark.components.TabBar;
	import spark.components.TextArea;
	import spark.primitives.Rect;
	import spark.utils.TextFlowUtil;
	
	/**
	 *  The ImageRotator class uses Pixel Bender effects, which are not supported
	 *  for AIR mobile applications.
	 */
	[DiscouragedForProfile("mobileDevice")]

	//--------------------------------------
	//  Other metadata
	//--------------------------------------
	
	[IconFile("assets/icons/ImageRotator.png")]

	/**
	 * The ImageRotator component displays multiple images in sequence using
	 * a list of shader effects. Image navigation can be controlled using a
	 * navigation bar or next/previous buttons.
	 */
	public class ImageRotator extends ImageRotatorBase
	{
		/**
		 * Constructor
		 */
		public function ImageRotator()
		{
			super();
		}
		
		//--------------------------------------------------------------------------
		//
		//  public functions
		//
		//--------------------------------------------------------------------------
		
		/**
		 *  @private
		 */
		override public function set selectedIndex(value:uint):void
		{
			super.selectedIndex = value;
			
			if(navBar)
				navBar.selectedIndex = value;
		}
		
		//--------------------------------------------------------------------------
		//
		//  protected functions
		//
		//--------------------------------------------------------------------------
		/**
		 * @private
		 */
		override protected function addHandlers():void
		{
			super.addHandlers();
			
			addEventListener(MouseEvent.ROLL_OVER, onRollOver);
			addEventListener(MouseEvent.ROLL_OUT, onRollOut);
		}
		
		/**
		 * @private
		 */
		protected var _isRollOver:Boolean = false;
		
		/**
		 * @private
		 */
		protected function onRollOver(event:MouseEvent):void
		{
			_isRollOver = true;
			
			if(navBar && navBarVisible)
			{
				navBar.visible = true;				
			}
			
			if(nextButton && previousButton && buttonsVisible)
			{
				nextButton.visible = true;
				previousButton.visible = true;
			}
			
			if(textDisplay && descriptionVisible && textDisplay.text != "")
			{
				textDisplay.visible = true;
			}
		}
		
		/**
		 * @private
		 */
		protected function onRollOut(event:MouseEvent):void
		{
			_isRollOver = false;
			
			if(navBar)
			{
				navBar.visible = false;				
			}
			
			if(nextButton && previousButton)
			{
				nextButton.visible = false;
				previousButton.visible = false;
			}
			
			if(textDisplay)
			{
				textDisplay.visible = false;
			}
		}
		
		/**
		 * @private
		 */
		override protected function onDataChange(event:FlexEvent = null):void
		{
			super.onDataChange(event);
			
			_previousSelectedIndex = -1;
			
			if(navBar)
				navBar.dataProvider = imagesList;				
		}
		
		/**
		 * @private
		 */
		override protected function childrenCreated():void
		{
			super.childrenCreated();
			
			if(imagesList)
				onDataChange();
		}
		
		/**
		 *  @private
		 */
		override protected function partAdded(partName:String, instance:Object):void
		{
			super.partAdded(partName, instance);
			
			if(instance == previousButton)
			{
				previousButton.alpha = 0;
				previousButton.visible = false;
				previousButton.addEventListener(MouseEvent.CLICK, onArrowClick);
			}else if(instance == nextButton)
			{
				nextButton.alpha = 0;
				nextButton.visible = false;
				nextButton.addEventListener(MouseEvent.CLICK, onArrowClick);
			}else if(instance == navBar)
			{
				navBar.alpha = 0;
				navBar.visible = false;
				navBar.addEventListener(MouseEvent.CLICK, onNavBarClick);
			}else if(instance == progressBar)
			{
				
			}else if(instance == textDisplay)
			{
				textDisplay.visible = false;
				textDisplay.alpha = 0;
				
			}else if(instance == imageContainer)
			{
				imageContainer.addEventListener(MouseEvent.CLICK, onImageContainerClick);
				
				_image0.addEventListener(ProgressEvent.PROGRESS, onImageLoadProgress, false, 0, true);
				_image1.addEventListener(ProgressEvent.PROGRESS, onImageLoadProgress, false, 0, true);
			}
		}
		
		/**
		 *  @private
		 */
		override protected function partRemoved(partName:String, instance:Object):void
		{
			super.partRemoved(partName, instance);
			
			if(instance == previousButton)
			{
				previousButton.removeEventListener(MouseEvent.CLICK, onArrowClick);
			}else if(instance == nextButton)
			{
				nextButton.removeEventListener(MouseEvent.CLICK, onArrowClick);
			}else if(instance == navBar)
			{
				navBar.removeEventListener(MouseEvent.CLICK, onNavBarClick);
			}else if(instance == progressBar)
			{
				
			}else if(instance == textDisplay)
			{
				
			}else if(instance == imageContainer)
			{
				imageContainer.removeEventListener(MouseEvent.CLICK, onImageContainerClick);
				
				_image0.removeEventListener(ProgressEvent.PROGRESS, onImageLoadProgress);
				_image1.removeEventListener(ProgressEvent.PROGRESS, onImageLoadProgress);					
			}
		}
		
		/**
		 * When the component is clicked, if the selected item includes an
		 * external url in its data, navigate to thet url
		 */
		protected function onImageContainerClick(event:MouseEvent):void
		{
			if(selectedItem)
			{
				var url:String = selectedItem.url.toString();
				var target:String = selectedItem.target.toString();
				navigateToURL(new URLRequest(url), target);
			}
		}
		
		/**
		 * @private
		 */
		private var _previousSelectedIndex:int = -1;
		
		/**
		 * When a thumb is clicked selects the corresponding item in the list
		 */
		protected function onNavBarClick(event:MouseEvent):void
		{
			if(navBar.selectedIndex >= 0 && navBar.selectedIndex != _previousSelectedIndex)
			{
				selectedIndex = navBar.selectedIndex;
				_previousSelectedIndex = selectedIndex;
			}
		}
		
		/**
		 * When a previous/next arrow is clicked, selects the corresponding action
		 */
		protected function onArrowClick(event:MouseEvent):void
		{
			if(event.target == nextButton && imagesList.length > 0)
			{
				setNextElement();
			}else if(event.target == previousButton && imagesList.length > 0)
			{
				setPreviousElement();
			}
		}
		
		/**
		 * Updates the progress bar during the loading process
		 */
		protected function onImageLoadProgress(event:ProgressEvent):void
		{
			if(progressBar)
				progressBar.scaleX = event.bytesLoaded / event.bytesTotal;
		}
		
		/**
		 * Plays the transition for the new image and starts the
		 * slide timer
		 */
		override protected function playTransition():void
		{
			var transition:Transition = new Transition();
			transition.effect = AnimateTransitionShaderUtils.getTransition(selectedItem.effect.toString(), imageContainer, selectedItem.params);
			imageContainer.transitions = [transition];
			imageContainer.currentState = (imageContainer.currentState == "flipped") ? "normal" : "flipped";
			
			_timer.start();
		}
		
		/**
		 * When an image has been loaded, play the corresponding transition
		 * 
		 * @param event
		 */
		override protected function onImageLoadComplete(event:Event):void
		{
			super.onImageLoadComplete(event);
			
			var txt:String = selectedItem.description.text();
			textDisplay.textFlow = TextFlowUtil.importFromString(txt);
			
			if(textDisplay.text && _isRollOver && descriptionVisible)
				textDisplay.visible = true;
			else
				textDisplay.visible = false;
			
			if(progressBar)
				progressBar.scaleX = 0;
		}
		
		//--------------------------------------------------------------------------
		//
		//  getters and setters
		//
		//--------------------------------------------------------------------------
		/**
		 * @private
		 */
		private var _navBarVisible:Boolean = true;
		
		/**
		 * If set to <code>true</code>, this flag will show the navbar
		 * when the image rotator is rolled over.
		 */
		[Bindable]
		public function get navBarVisible():Boolean
		{
			return _navBarVisible;
		}
		
		public function set navBarVisible(value:Boolean):void
		{
			_navBarVisible = value;
		}
		
		/**
		 * @private
		 */
		private var _buttonsVisible:Boolean = true;
		
		/**
		 * If set to <code>true</code>, this flag will show the next and previous buttons
		 * when the image rotator is rolled over.
		 */
		[Bindable]
		public function get buttonsVisible():Boolean
		{
			return _buttonsVisible;
		}
		
		public function set buttonsVisible(value:Boolean):void
		{
			_buttonsVisible = value;
		}
		
		/**
		 * @private
		 */
		private var _descriptionVisible:Boolean = true;
		
		/**
		 * If set to <code>true</code>, this flag will show the text display description
		 * when the image rotator is rolled over.
		 */
		[Bindable]
		public function get descriptionVisible():Boolean
		{
			return _descriptionVisible;
		}
		
		public function set descriptionVisible(value:Boolean):void
		{
			_descriptionVisible = value;
		}
		
		//--------------------------------------------------------------------------
		//
		//  skin parts
		//
		//--------------------------------------------------------------------------
		
		[SkinPart(required="false")]		
		/**
		 *  A skin part that defines the previous button. 
		 */
		public var previousButton:Button;
		
		[SkinPart(required="false")]
		/**
		 *  A skin part that defines the next button. 
		 */
		public var nextButton:Button;
		
		[SkinPart(required="false")]
		/**
		 *  A skin part that defines the thumbnails navbar. 
		 */
		public var navBar:TabBar;
		
		[SkinPart(required="false")]
		/**
		 *  A skin part that displays the image description. 
		 */
		public var textDisplay:TextArea;
		
		[SkinPart(required="false")]		
		/**
		 *  A skin part that defines the loading progress. 
		 */
		public var progressBar:Rect;
		
	}
}